package com.thiagov.poc;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;
import android.util.Log;

/**
 * Classe utilizada para manipular os dados de um banco de dados SQLite.
 * @author thiagov
 *
 */
public class DataHelper {

    /** Nome e versao do bonco de dados a ser utilizado na aplicacao. */
    private static final String DATABASE_NAME = "AppDB.db";
    private static final int DATABASE_VERSION = 2;

    /** Tabelas do banco de dados. */
    private static final String TABLE_NAME = "places";
    private static final String SECOND_TABLE_NAME = "quests";

    /** Contexto do banco de dados e instancia do banco. */
    private Context context;
    private SQLiteDatabase db;

    /** Statements necessarios para realizar a insercao no banco de dados. */
    private SQLiteStatement insertStmt;
    private SQLiteStatement secondInsertStmt;

    /** Comandos de insert para cada tabela do banco de dados. */
    private static final String PLACES_INSERT = "insert into "
       + TABLE_NAME + " (name, addr, description, active, tourVisited, lat, lng, infoLink) values (?, ?, ?, ?, ?, ?, ?, ?)";
    private static final String QUESTS_INSERT = "insert into "
        + SECOND_TABLE_NAME + " (place_id, name, done, type) values (?, ?, ?, ?)";

    /**
     * Construtor da classe.
     * @param context
     *        O contexto a ser utilizado.
     */
    public DataHelper(Context context) {
        this.context = context;
        OpenHelper openHelper = new OpenHelper(this.context);
        this.db = openHelper.getWritableDatabase();
        this.insertStmt = this.db.compileStatement(PLACES_INSERT);
        this.secondInsertStmt = this.db.compileStatement(QUESTS_INSERT);
    }

    /**
     * Metodo utilizado para inserir dados na tabela que representa os Places
     * do banco de dados.
     * @param name
     *        Nome do lugar.
     * @param addr
     *        Endereco do local.
     * @param description
     *        Descricao do local.
     * @param active
     *        Indica se o local esta ou nao ativo.
     * @param tourVisited
     *        Indica se o local ja foi visitado na quest de 'Tour'
     * @param lat
     *        Latitude do local.
     * @param lng
     *        Longitude do local.
     * @param infoLink
     *        O link para uma pagina contendo informacoes do local.
     * @return o ID da ultima linha inserida na tabela.
     */
    public long placesInsert(String name, String addr, String description, boolean active, boolean tourVisited, int lat, int lng, String infoLink) {
        this.insertStmt.bindString(1, name);
        this.insertStmt.bindString(2, addr);
        this.insertStmt.bindString(3, description);
        this.insertStmt.bindString(4, active? "True" : "False");
        this.insertStmt.bindString(5, tourVisited? "True" : "False");
        this.insertStmt.bindLong(6, lat);
        this.insertStmt.bindLong(7, lng);
        this.insertStmt.bindString(8, infoLink);
        return this.insertStmt.executeInsert();
    }

    /**
     * Metodo utilizado para inserir na tabela que representa as Quests do banco
     * de dados.
     * @param placeId
     *        ID do local que possui tal quest.
     * @param name
     *        Nome da quest.
     * @param done
     *        Valor booleano que indica se a quest ja foi ou nao realizada.
     * @param type
     *        Tipo da ques. Ex.: Foto, Compartilhamento, etc.
     * @return o ID da ultima linha inserida na tabela.
     */
    public long questsInsert(int placeId, String name, boolean done, int type) {
        this.secondInsertStmt.bindLong(1, placeId);
        this.secondInsertStmt.bindString(2, name);
        this.secondInsertStmt.bindString(3, done? "True" : "False");
        this.secondInsertStmt.bindLong(4, type);
        return this.secondInsertStmt.executeInsert();        
    }

    /**
     * Deleta todos os dados de todas as tabelas do banco de dados.
     */
    public void deleteAll() {
        this.db.delete(TABLE_NAME, null, null);
        this.db.delete(SECOND_TABLE_NAME, null, null);
    }

    /**
     * Retorna a instancia do banco de dados, para permitir a realizacao
     * de buscas diretamente.
     * @return a isntancia do banco de dados usado na aplicacao.
     */
    public SQLiteDatabase getDatabase() {
        return db;
    }

    /**
     * Classe utilizada para a criacao de um banco de dados SQLite.
     * @author thiagov
     *
     */
    private static class OpenHelper extends SQLiteOpenHelper {

        /**
         * Construtor da classe.
         * @param context
         *        O contexto a ser utilizado.
         */
        public OpenHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        /**
         * Cria as tabelas do banco de dados.
         */
        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL("CREATE TABLE " + TABLE_NAME + "(id INTEGER PRIMARY KEY, name TEXT, addr TEXT, description TEXT, active BOOLEAN, tourVisited BOOLEAN, lat INTEGER, lng INTEGER, infoLink TEXT)");
            String query = "CREATE TABLE " + SECOND_TABLE_NAME +
            " (id INTEGER PRIMARY KEY," +
            " place_id INTEGER," +
            " name TEXT," +
            " done BOOLEAN," +
            " type INTEGER," +
            " FOREIGN KEY (place_id) REFERENCES " + TABLE_NAME + " (id))";
            db.execSQL(query);
        }

        /**
         * Metodo chamado quando o banco eh atualizado.
         */
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            Log.w("Example", "Upgrading database, this will drop tables and recreate.");
            db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
            db.execSQL("DROP TABLE IF EXISTS " + SECOND_TABLE_NAME);
            onCreate(db);
        }
    }
 }